home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / libscsi1.zoo / LibScsi-0.01 / scsicmd.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-15  |  12.2 KB  |  346 lines

  1. #APP
  2. |
  3. | scsicmd.s - Copyright Steve Woodford, August 1993.
  4. | SCSI Device Access functions. 32/16 bit ints.
  5. |
  6. | This code supports only the ST(E)s ACSI port. Support for Falcon and
  7. | TT would be nice, but as I dont have one of those....
  8. |
  9. |
  10. | Declare entry points and exported variables...
  11. |
  12.             .globl  __Scsi_Timeout
  13.             .globl  __Scsi_Command
  14.             .globl  __Scsi_Read_Bytes
  15.             .globl  __Scsi_Dma_Len
  16. |
  17.             .text
  18.             .even
  19. |
  20. |
  21. |*****************************************************************************
  22. |
  23. |   short   _Scsi_Timeout(secs)
  24. |           short   secs;
  25. |
  26. | Modify the timeout value to use for the next SCSI command.
  27. |
  28. __Scsi_Timeout:
  29.             movew   Lscsi_timeout,d0
  30.             extl    d0
  31. #ifdef    __MSHORT__
  32.             movew   sp@(4),Lscsi_timeout
  33. #else
  34.             movew   sp@(6),Lscsi_timeout
  35. #endif
  36.             rts
  37. |
  38. |
  39. |*****************************************************************************
  40. |
  41. |   short   _Scsi_Command(rw, cmd_buf, transfer_addr, length)
  42. |           int          rw;
  43. |           Scsi_Cmd    *cmd_buf;
  44. |           void        *transfer_addr;
  45. |           int          sectors;
  46. |
  47. | This function is used when to issue a SCSI command to a target.
  48. | The function returns the SCSI targets completion code, or -1 if timeout.
  49. | Note that "transfer_addr" must be on a word boundary.
  50. |
  51. __Scsi_Command:
  52. #ifdef    __MSHORT__
  53.             movew   sp@(4),rw_flag      | Save read/write flag
  54.             movel   sp@(6),cmd_buff     | Save command buffer pointer
  55.             movel   sp@(10),d1          | Get transfer address
  56. #else
  57.             movew   sp@(6),rw_flag      | Save read/write flag
  58.             movel   sp@(8),cmd_buff     | Save command buffer pointer
  59.             movel   sp@(12),d1          | Get transfer address
  60. #endif
  61.             bne     Lgood_addr          | Jump if Ok
  62.             movel   #sec_buff,d1
  63. Lgood_addr:
  64.             movel   d1,tr_addr          | Save transfer address
  65. #ifdef    __MSHORT__
  66.             movew   sp@(14),d0          | Get transfer length
  67. #else
  68.             movew   sp@(18),d0          | Get transfer length
  69. #endif
  70.             bgt     Ldma_sect           | Jump if transferring sectors
  71.             moveql  #1,d0               | Transfer only 1 
  72. Ldma_sect:
  73.             movew   d0,tr_length        | Save sector count
  74.             movew   #0xffff,comp_code   | Assume error!
  75.             clrw    keep_flock          | Ensure "flock" cleared on exit
  76.             st      reset_dma           | Ensure DMA reset
  77.             moveml  d1-d2/a2,sp@-       | Save bdos trashed registers
  78. |
  79. | Following code added to be compatible with Mint. Previously, xbios SUPERX
  80. | was used, which doesnt work under Mint <sigh>.
  81. |
  82.             link    a6,#0
  83.             clrl    sp@-
  84.             movew   #0x20,sp@-
  85.             trap    #1
  86.             addqw   #6,sp
  87.             movel   d0,sp@-
  88.             jbsr    Lscsi_command
  89.             movew   #0x20,sp@-
  90.             trap    #1
  91.             addqw   #6,sp
  92.             unlk    a6
  93. |
  94. |
  95.             moveml  sp@+,d1-d2/a2       | Restore regs
  96.             movel   tr_addr,d0          | Get final DMA address
  97.             subl    d1,d0               | Compute length of transfer
  98.             moveql  #9,d1
  99.             lsrl    d1,d0               | Compute in dma sectors
  100.             movew   d0,__Scsi_Dma_Len   | Save it
  101.             movew   comp_code,d0        | Fetch completion code
  102.             extl    d0
  103.             rts
  104. |
  105. Lscsi_command:
  106.             st      0x43e:w             | Set "flock"
  107.             lea     0x8604:w,a0         | DMA Controller Data Register
  108.             lea     0x8606:w,a1         | DMA Status/Control Register
  109.             movel   cmd_buff,a2         | Get pointer to command buffer
  110.             moveql  #0,d2               | d2 == 0 for read, else 0x0100
  111.             moveql  #1,d1
  112.             cmpw    rw_flag,d1
  113.             bne     Lrc_nowr
  114.             movew   #0x0100,d2          | Flag "write"
  115. Lrc_nowr:
  116.             movel   0x4ba:w,d0          | 200Hz counter
  117.             addql   #4,d0               | Got to wait about 1/50th second
  118. Lrc_delay:
  119.             cmpl    0x4ba:w,d0          | Delay over?
  120.             bcc     Lrc_delay           | Back if not
  121.             tstw    reset_dma           | Reset DMA stuff?
  122.             beq     Lrc_no_reset        | Jump if not
  123.             movel   tr_addr,sp@-        | Stack transfer address
  124.             moveb   sp@(3),a1@(7)
  125.             moveb   sp@(2),a1@(5)
  126.             moveb   sp@(1),a1@(3)
  127.             addqw   #4,sp
  128.             movew   #0x0098,d0
  129.             movew   d0,a1@              | Toggle Read/Write
  130.             movew   #0x0198,a1@
  131.             movew   d0,a1@
  132.             orw     d2,d0               | Include "write" bit in DMA code
  133.             movew   d0,a1@              | Store it
  134.             movew   tr_length,a0@       | Store sector count
  135. Lrc_no_reset:
  136.             movew   #0x0088,d0          | Prime for Acsi command code
  137.             orw     d2,d0               | Include write bit
  138.             movew   d0,a1@
  139.             clrw    d0
  140.             moveb   a2@+,d0             | Fetch SCSI command code
  141.             swap    d0
  142.             movew   #0x008a,d0          | Prepare to send command code
  143.             orw     d2,d0               | Include write bit
  144.             movel   d0,a0@              | Send it
  145.             bsr     Lreq_wait1          | Wait for interrupt
  146.             bmi     Lrc_end             | Abort if timeout
  147.             swap    d0
  148.             moveb   a2@+,d0             | Command byte 1
  149.             swap    d0
  150.             movel   d0,a0@              | Store it
  151.             bsr     Lreq_wait1          | Wait for interrupt
  152.             bmi     Lrc_end             | Abort if timeout
  153.             swap    d0
  154.             moveb   a2@+,d0             | Command byte 2
  155.             swap    d0
  156.             movel   d0,a0@              | Store it
  157.             bsr     Lreq_wait1          | Wait for interrupt
  158.             bmi     Lrc_end             | Abort if timeout
  159.             swap    d0
  160.             moveb   a2@+,d0             | Command byte 3
  161.             swap    d0
  162.             movel   d0,a0@              | Store it
  163.             bsr     Lreq_wait1          | Wait for interrupt
  164.             bmi     Lrc_end             | Abort if timeout
  165.             swap    d0
  166.             moveb   a2@+,d0             | Command byte 4
  167.             swap    d0
  168.             movel   d0,a0@              | Store it
  169.             bsr     Lreq_wait1          | Wait for interrupt
  170.             bmi     Lrc_end             | Abort if timeout
  171.             moveb   a2@+,d0             | Command byte 5
  172.             swap    d0
  173.             movew   d2,d0               | Initiate command
  174.             movel   d0,a0@              | Store it
  175. |
  176. | Target should now be transferring over DMA bus
  177. |
  178.             movew   Lscsi_timeout,d2    | Max # of seconds to wait
  179. Lrc_wait:
  180.             movel   #200,d1             | 1 second delay
  181.             bsr     Lreq_wait2          | Wait for command complete
  182.             bpl     Lrc_ok              | Jump if Ok
  183.             dbra    d2,Lrc_wait         | Back if not
  184. |
  185. | Lets do all we can to reset Scsi bus...
  186. |
  187.             movew   #0x008a,a1@
  188.             nop
  189.             tstw    a0@
  190.             nop
  191.             movew   #0x0098,a1@
  192.             movew   #0x0198,a1@
  193.             movew   #0x0098,a1@
  194.             nop
  195.             movew   #0x008a,a1@
  196.             bra     Lrc_end
  197. Lrc_ok:
  198.             clrl    sp@-                | Make a slot on the stack
  199.             moveb   a1@(7),sp@(3)       | Fetch final DMA address
  200.             moveb   a1@(5),sp@(2)
  201.             moveb   a1@(3),sp@(1)
  202.             movel   sp@+,tr_addr        | Store it
  203.             movew   #0x008a,a1@         | Prepare to fetch completion code
  204.             nop
  205.             movew   a0@,d0              | Get it
  206.             andw    #0x00ff,d0          | Only want low 8 bits
  207.             movew   d0,comp_code        | Store it
  208. Lrc_end:
  209.             movew   #0x0080,a1@         | Reset DMA
  210.             nop
  211.             tstw    a0@                 | Clear DMA completion code
  212.             tstw    keep_flock          | Should we clear "flock"?
  213.             bne     Lrc_exit            | Jump if not
  214. Lclr_flock:
  215.             clrw    0x43e:w             | Clear "flock"
  216. Lrc_exit:
  217.             rts
  218. |
  219. |
  220. Lreq_wait1:
  221.             moveql  #10,d1              | 50mS timeout
  222. Lreq_wait2:
  223.             addl    0x4ba:w,d1          | Used to compute timeout
  224. Lreq_wait3:
  225.             btst    #5,0xfa01:w
  226.             beq     Lreq_done
  227.             cmpl    0x4ba:w,d1          | Timed out?
  228.             bcc     Lreq_wait3          | Jump if not
  229. Lreq_done:
  230.             rts
  231. |
  232. |
  233. |*****************************************************************************
  234. |
  235. |   short   _Scsi_Read_Bytes( cmd_buf, transfer_addr, length )
  236. |           Scsi_Cmd    *cmd_buf;
  237. |           void        *transfer_addr;
  238. |           short        bytes;
  239. |
  240. | This function is used to issue a SCSI command which transfers less
  241. | than 512 bytes of data. This is a pain in the ST as the DMA chip buffers
  242. | 8 bytes internally, so we may have to issue the command several times
  243. | to get the full response we require. Either way, we use a temporary
  244. | buffer so as not to overrun the users buffer.
  245. |
  246. __Scsi_Read_Bytes:
  247.             movel   sp@(4),cmd_buff     | Save command buffer pointer
  248.             movel   #sec_buff,tr_addr   | Use sector buffer for transfer
  249.             movew   #1,tr_length        | 1 sector, max, to transfer
  250.             st      reset_dma           | Signal "reset DMA"
  251.             st      keep_flock          | Keep hold of "flock"
  252.             clrw    rw_flag             | Read only
  253.             movew   #16,ss_retry        | # of retries
  254. Lss_get:
  255.             movew   #0xffff,comp_code   | Assume error!
  256.             subqw   #1,ss_retry
  257.             bmi     Lss_done
  258.             moveml  d2/a2,sp@-          | Save bdos trashed registers
  259. |
  260. | Following code added to be compatible with Mint. Previously, xbios SUPERX
  261. | was used, which doesnt work under Mint <sigh>.
  262. |
  263.             link    a6,#0
  264.             clrl    sp@-
  265.             movew   #0x20,sp@-
  266.             trap    #1
  267.             addqw   #6,sp
  268.             movel   d0,sp@-
  269.             jbsr    Lscsi_command
  270.             movew   #0x20,sp@-
  271.             trap    #1
  272.             addqw   #6,sp
  273.             unlk    a6
  274. |
  275. |
  276.             moveml  sp@+,d2/a2          | Restore regs
  277.             clrw    reset_dma           | No more DMA resets, for now
  278.             tstw    comp_code           | Timeout?
  279.             bmi     Lss_done            | Yes!
  280.             movel   tr_addr,d0          | Get current DMA address
  281.             subl    #sec_buff,d0        | d0 == # of bytes transferred
  282. #ifdef    __MSHORT__
  283.             cmpw    sp@(12),d0          | Got all we want?
  284. #else
  285.             cmpw    sp@(14),d0          | Got all we want?
  286. #endif
  287.             blt     Lss_get             | Nope. Try again!
  288. Lss_done:
  289.             movel   sp@(8),a1           | Get dest. buffer address
  290. #ifdef    __MSHORT__
  291.             movew   sp@(12),d1          | Get # of bytes required
  292. #else
  293.             movew   sp@(14),d1          | Get # of bytes required
  294. #endif
  295.             cmpw    d0,d1               | Get minimum
  296.             bge     Lss_gt
  297.             movew   d1,d0
  298. Lss_gt:
  299.             lea     sec_buff,a0
  300.             bra     Lss_enter
  301. Lss_cloop:
  302.             moveb   a0@+,a1@+           | Copy accross
  303. Lss_enter:
  304.             dbra    d0,Lss_cloop
  305.             moveml  d2/a2,sp@-
  306. |
  307. | Following code added to be compatible with Mint. Previously, xbios SUPERX
  308. | was used, which doesnt work under Mint <sigh>.
  309. |
  310.             link    a6,#0
  311.             clrl    sp@-
  312.             movew   #0x20,sp@-
  313.             trap    #1
  314.             addqw   #6,sp
  315.             movel   d0,sp@-
  316.             jbsr    Lclr_flock
  317.             movew   #0x20,sp@-
  318.             trap    #1
  319.             addqw   #6,sp
  320.             unlk    a6
  321. |
  322. |
  323.             moveml  sp@+,d2/a2
  324.             movew   comp_code,d0        | Fetch completion code
  325.             extl    d0
  326.             rts
  327. |
  328. |*****************************************************************************
  329. |
  330.             .data
  331.             .even
  332. Lscsi_timeout:
  333.             .word   10                  | Default to 10 second timeout
  334. |
  335. .comm       __Scsi_Dma_Len,2            | DMA blocks transferred goes here
  336. |
  337. .lcomm      cmd_buff,4
  338. .lcomm      tr_addr,4
  339. .lcomm      tr_length,2
  340. .lcomm      rw_flag,2
  341. .lcomm      comp_code,2
  342. .lcomm      reset_dma,2
  343. .lcomm      ss_retry,2
  344. .lcomm      keep_flock,2
  345. .lcomm      sec_buff,512
  346.